package com.centsuse.my_redis.config.serializers;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.io.IOException;
import java.util.Date;

/**
 * @author bobo
 */
public class CustomJsonRedisSerializer implements RedisSerializer<Object> {

    private final ObjectMapper objectMapper;

    public CustomJsonRedisSerializer() {
        this.objectMapper = new ObjectMapper();
        // 禁用Jackson的默认类型信息注入，这是避免 ["java.util.Date", 1757517035000] 这种格式的关键
        // objectMapper.activateDefaultTyping(...); // 不要调用此方法

        // 创建一个模块，专门用于处理Date类型的序列化和反序列化
        SimpleModule module = new SimpleModule();
        // 为Date类型注册自定义序列化器：输出为时间戳（long）
        module.addSerializer(Date.class, new JsonSerializer<Date>() {
            @Override
            public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                gen.writeNumber(value.getTime()); // 直接写入时间戳
            }
        });
        // 为Date类型注册自定义反序列化器：从时间戳（long）还原为Date对象
        module.addDeserializer(Date.class, new JsonDeserializer<Date>() {
            @Override
            public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                return new Date(p.getLongValue());
            }
        });

        objectMapper.registerModule(module);
        // 其他可能需要的配置，例如禁用日期格式化为字符串
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    }

    @Override
    public byte[] serialize(Object object) throws SerializationException {
        if (object == null) {
            return new byte[0];
        }
        try {
            return objectMapper.writeValueAsBytes(object);
        } catch (Exception e) {
            throw new SerializationException("Could not serialize: " + e.getMessage(), e);
        }
    }

    @Override
    public Object deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        try {
            // 注意：这里反序列化时需要目标类型信息，通常由Spring缓存方法返回类型或RedisTemplate的泛型提供
            return objectMapper.readValue(bytes, Object.class);
        } catch (Exception e) {
            throw new SerializationException("Could not deserialize: " + e.getMessage(), e);
        }
    }
}